import { Router } from "express";
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import type { Secret, SignOptions } from 'jsonwebtoken';
import axios from 'axios';
import crypto from 'crypto';
import { authenticateWxAppToken } from "../middleware/wxapp-auth";
import { MongoDBService } from "../services/mongodb-service";

const router = Router();

// 环境变量配置（对 jsonwebtoken v9 类型做显式注解）
const AUTH_SECRET_WXAPP: Secret = (process.env.AUTH_SECRET_WXAPP as unknown as Secret) || 'wxapp-secret-key-medical-2024';
const WXAPP_ACCESS_TTL: SignOptions['expiresIn'] = (process.env.WXAPP_ACCESS_TTL as any) || '24h';
const WXAPP_REFRESH_TTL: SignOptions['expiresIn'] = (process.env.WXAPP_REFRESH_TTL as any) || '30d';

// MongoDB 服务实例
const mongoService = new MongoDBService();

// 工具函数：生成 wxapp access token
function generateWxAppAccessToken(userId: string, roles: string[]): string {
  return jwt.sign(
    { 
      userId, 
      roles,
      aud: 'wxapp',
      iss: 'medical-system'
    },
    AUTH_SECRET_WXAPP,
    { expiresIn: WXAPP_ACCESS_TTL }
  );
}

// 工具函数：生成 wxapp refresh token
async function generateWxAppRefreshToken(userId: string): Promise<string> {
  const token = jwt.sign(
    { 
      userId,
      aud: 'wxapp',
      iss: 'medical-system',
      type: 'refresh'
    },
    AUTH_SECRET_WXAPP,
    { expiresIn: WXAPP_REFRESH_TTL }
  );

  // 存储到MongoDB
  const expiresAt = new Date();
  expiresAt.setDate(expiresAt.getDate() + 7); // 7天有效期
  
  await mongoService.saveWxRefreshToken({
    token,
    userId,
    expiresAt
  });

  return token;
}

// 工具函数：验证 wxapp refresh token
async function validateWxAppRefreshToken(token: string): Promise<{ valid: boolean; userId?: string }> {
  try {
    const stored = await mongoService.getWxRefreshToken(token);
    if (!stored) {
      return { valid: false };
    }

    const decoded = jwt.verify(token, AUTH_SECRET_WXAPP) as any;
    if (decoded.aud !== 'wxapp' || decoded.type !== 'refresh') {
      return { valid: false };
    }

    return { valid: true, userId: decoded.userId };
  } catch (error) {
    return { valid: false };
  }
}

// 工具函数：密码哈希
async function hashPassword(password: string): Promise<string> {
  return await bcrypt.hash(password, 12);
}

// 工具函数：验证密码
async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return await bcrypt.compare(password, hash);
}

// 生成用户ID
function generateUserId(): string {
  return 'wx_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
}

// 初始化测试用户
async function initTestUsers() {
  try {
    const existingUser = await mongoService.getWxUserByPhone('13800000001');
    if (!existingUser) {
      const testUser = {
        id: generateUserId(),
        phone: '13800000001',
        passwordHash: await hashPassword('123456'),
        nickname: '测试用户',
        avatar: '/static/images/default-avatar.png',
        status: 'active' as const,
        roles: ['wx_user'],
        createdAt: new Date(),
        updatedAt: new Date()
      };
      
      await mongoService.createWxUser(testUser);
      console.log('[wxapp] 初始化测试用户:', testUser.phone);
    }
  } catch (error) {
    console.error('[wxapp] 初始化测试用户失败:', error);
  }
}

// 初始化
initTestUsers();

// wxapp 用户注册
router.post("/register", async (req, res) => {
  try {
    const { phone, password, nickname } = req.body;

    if (!phone || !password) {
      return res.status(400).json({
        success: false,
        message: "手机号和密码都是必填项"
      });
    }

    // 检查手机号格式
    const phoneRegex = /^1[3-9]\d{9}$/;
    if (!phoneRegex.test(phone)) {
      return res.status(400).json({
        success: false,
        message: "手机号格式不正确"
      });
    }

    // 检查用户是否已存在
    const existingUser = await mongoService.getWxUserByPhone(phone);
    if (existingUser) {
      return res.status(400).json({
        success: false,
        message: "该手机号已注册"
      });
    }

    // 创建新用户
    const userId = generateUserId();
    const passwordHash = await hashPassword(password);
    
    const newUser = await mongoService.createWxUser({
      id: userId,
      phone,
      passwordHash,
      nickname: nickname || `用户${phone.slice(-4)}`,
      avatar: '/static/images/default-avatar.png',
      status: 'active' as const,
      roles: ['wx_user'],
      createdAt: new Date(),
      updatedAt: new Date()
    });

    // 生成令牌
    const accessToken = generateWxAppAccessToken(userId, newUser.roles);
    const refreshToken = await generateWxAppRefreshToken(userId);

    console.log(`[wxapp注册] 新用户: ${phone} (${newUser.nickname})`);

    return res.json({
      success: true,
      user: {
        id: newUser.id,
        phone: newUser.phone,
        nickname: newUser.nickname,
        avatar: newUser.avatar,
        roles: newUser.roles,
        status: newUser.status
      },
      tokens: {
        accessToken,
        refreshToken
      }
    });

  } catch (error: any) {
    console.error("wxapp注册错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// wxapp 用户登录
router.post("/login", async (req, res) => {
  try {
    const { phone, password } = req.body;

    if (!phone || !password) {
      return res.status(400).json({
        success: false,
        message: "手机号和密码都是必填项"
      });
    }

    // 查找用户
    const foundUser = await mongoService.getWxUserByPhone(phone);
    if (!foundUser) {
      return res.status(400).json({
        success: false,
        message: "手机号或密码错误"
      });
    }

    // 检查用户状态
    if (foundUser.status === 'frozen') {
      return res.status(403).json({
        success: false,
        message: "账号已被冻结，请联系管理员"
      });
    }

    // 验证密码
    const passwordValid = await verifyPassword(password, foundUser.passwordHash);
    if (!passwordValid) {
      return res.status(400).json({
        success: false,
        message: "手机号或密码错误"
      });
    }

    // 更新最后登录时间
    await mongoService.updateWxUser(foundUser.id, {
      lastLoginAt: new Date(),
      updatedAt: new Date()
    });

    // 生成令牌
    const accessToken = generateWxAppAccessToken(foundUser.id, foundUser.roles);
    const refreshToken = await generateWxAppRefreshToken(foundUser.id);

    console.log(`[wxapp登录] 用户: ${foundUser.phone} (${foundUser.nickname})`);

    return res.json({
      success: true,
      user: {
        id: foundUser.id,
        phone: foundUser.phone,
        nickname: foundUser.nickname,
        avatar: foundUser.avatar,
        roles: foundUser.roles,
        status: foundUser.status
      },
      tokens: {
        accessToken,
        refreshToken
      }
    });

  } catch (error: any) {
    console.error("wxapp登录错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// wxapp 刷新令牌
router.post("/refresh", async (req, res) => {
  try {
    const { refreshToken } = req.body;

    if (!refreshToken) {
      return res.status(400).json({
        success: false,
        message: "缺少 refresh token"
      });
    }

    const validation = await validateWxAppRefreshToken(refreshToken);
    if (!validation.valid) {
      return res.status(401).json({
        success: false,
        message: "无效或过期的 refresh token"
      });
    }

    const userId = validation.userId as string;
    const foundUser = await mongoService.getWxUserById(userId);

    if (!foundUser) {
      return res.status(404).json({
        success: false,
        message: "用户不存在"
      });
    }

    if (foundUser.status === 'frozen') {
      return res.status(403).json({
        success: false,
        message: "账号已被冻结"
      });
    }

    // 生成新的令牌（实现令牌轮换）
    const newAccessToken = generateWxAppAccessToken(userId, foundUser.roles);
    const newRefreshToken = await generateWxAppRefreshToken(userId);

    // 删除旧的 refresh token
    await mongoService.deleteWxRefreshToken(refreshToken);

    console.log(`[wxapp刷新] 用户: ${foundUser.phone} 获取了新的令牌`);

    return res.json({
      success: true,
      accessToken: newAccessToken,
      refreshToken: newRefreshToken
    });

  } catch (error: any) {
    console.error("wxapp刷新令牌错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// wxapp 登出
router.post("/logout", async (req, res) => {
  try {
    const { refreshToken } = req.body;

    if (refreshToken) {
      // 删除 refresh token
      await mongoService.deleteWxRefreshToken(refreshToken);
      console.log(`[wxapp登出] refresh token 已删除`);
    }

    return res.json({
      success: true,
      message: "登出成功"
    });

  } catch (error: any) {
    console.error("wxapp登出错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// 微信登录：前端传入 wx.login 获取的 code，这里向微信服务器换取 openid/session_key
router.post("/wechat-login", async (req, res) => {
  try {
    const { code, userInfo } = req.body;

    if (!code) {
      return res.status(400).json({ success: false, message: "缺少 code" });
    }

    const appid = process.env.WX_APPID;
    const secret = process.env.WX_SECRET;
    if (!appid || !secret) {
      return res.status(500).json({ success: false, message: "未配置微信AppID/Secret" });
    }

    // 调用微信 jscode2session 接口
    const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`;
    const wxResp = await axios.get(url);
    const { openid, unionid } = wxResp.data || {};

    if (!openid) {
      return res.status(401).json({ success: false, message: "微信登录失败" });
    }

    // 根据 openid 查找或创建用户
    let foundUser = await mongoService.getWxUserByOpenId(openid);

    if (!foundUser) {
      // 创建新用户（无手机号，允许后续绑定）
      const userId = generateUserId();
      const nickname = (userInfo && (userInfo.nickname || userInfo.nickName)) || `微信用户${String(openid).slice(-4)}`;
      const avatar = (userInfo && (userInfo.avatar || userInfo.avatarUrl)) || '/static/images/default-avatar.png';

      foundUser = await mongoService.createWxUser({
        id: userId,
        // phone 字段为空时不传入，MongoDB会自动忽略
        passwordHash: await hashPassword(crypto.randomBytes(6).toString('hex')),
        nickname,
        avatar,
        status: 'active' as const,
        roles: ['wx_user'],
        createdAt: new Date(),
        updatedAt: new Date(),
        wechatOpenId: openid,
        unionId: unionid
      });
      console.log(`[wxapp微信注册] openid=${openid}, uid=${userId}`);
    }

    // 更新登录时间
    foundUser = await mongoService.updateWxUser(foundUser.id, {
      lastLoginAt: new Date(),
      updatedAt: new Date()
    }) || foundUser;

    // 发放令牌
    const accessToken = generateWxAppAccessToken(foundUser.id, foundUser.roles);
    const refreshToken = await generateWxAppRefreshToken(foundUser.id);

    return res.json({
      success: true,
      user: {
        id: foundUser.id,
        phone: foundUser.phone,
        nickname: foundUser.nickname,
        avatar: foundUser.avatar,
        roles: foundUser.roles,
        status: foundUser.status
      },
      tokens: { accessToken, refreshToken }
    });

  } catch (error) {
    console.error('wxapp 微信登录错误:', error);
    return res.status(500).json({ success: false, message: '服务器内部错误' });
  }
});

// 获取当前用户信息（需要认证）
router.get("/profile", authenticateWxAppToken, async (req, res) => {
  try {
    // 这个路由需要使用 wxapp-auth 中间件
    const wxUser = (req as any).wxUser;
    if (!wxUser) {
      return res.status(401).json({
        success: false,
        message: "未认证的wxapp用户"
      });
    }

    const foundUser = await mongoService.getWxUserById(wxUser.id);
    if (!foundUser) {
      return res.status(404).json({
        success: false,
        message: "用户不存在"
      });
    }

    return res.json({
      success: true,
      user: {
        id: foundUser.id,
        phone: foundUser.phone,
        nickname: foundUser.nickname,
        avatar: foundUser.avatar,
        roles: foundUser.roles,
        status: foundUser.status,
        lastLoginAt: foundUser.lastLoginAt,
        createdAt: foundUser.createdAt
      }
    });

  } catch (error: any) {
    console.error("获取wxapp用户信息错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// 兼容小程序：POST /profile 与 GET /profile 相同逻辑
router.post("/profile", authenticateWxAppToken, async (req, res) => {
  try {
    // 这个路由需要使用 wxapp-auth 中间件
    const wxUser = (req as any).wxUser;
    if (!wxUser) {
      return res.status(401).json({
        success: false,
        message: "未认证的wxapp用户"
      });
    }

    const foundUser = await mongoService.getWxUserById(wxUser.id);
    if (!foundUser) {
      return res.status(404).json({
        success: false,
        message: "用户不存在"
      });
    }

    return res.json({
      success: true,
      user: {
        id: foundUser.id,
        phone: foundUser.phone,
        nickname: foundUser.nickname,
        avatar: foundUser.avatar,
        roles: foundUser.roles,
        status: foundUser.status,
        lastLoginAt: foundUser.lastLoginAt,
        createdAt: foundUser.createdAt
      }
    });

  } catch (error: any) {
    console.error("获取wxapp用户信息错误:", error);
    return res.status(500).json({
      success: false,
      message: "服务器内部错误"
    });
  }
});

// 更新当前用户信息（需要认证）
router.put("/profile", authenticateWxAppToken, async (req, res) => {
  try {
    const wxUser = (req as any).wxUser;
    if (!wxUser) {
      return res.status(401).json({ success: false, message: "未认证的wxapp用户" });
    }

    const { nickname, avatar } = req.body || {};

    const foundUser = await mongoService.getWxUserById(wxUser.id);
    if (!foundUser) {
      return res.status(404).json({ success: false, message: "用户不存在" });
    }

    const updateData: any = {};
    if (typeof nickname === 'string' && nickname.trim()) {
      updateData.nickname = nickname.trim();
    }
    if (typeof avatar === 'string' && avatar.trim()) {
      updateData.avatar = avatar.trim();
    }

    if (Object.keys(updateData).length === 0) {
      return res.status(400).json({ success: false, message: "没有需要更新的内容" });
    }

    updateData.updatedAt = new Date();
    const updatedUser = await mongoService.updateWxUser(foundUser.id, updateData);

    return res.json({
      success: true,
      user: {
        id: updatedUser!.id,
        phone: updatedUser!.phone,
        nickname: updatedUser!.nickname,
        avatar: updatedUser!.avatar,
        roles: updatedUser!.roles,
        status: updatedUser!.status,
        lastLoginAt: updatedUser!.lastLoginAt,
        createdAt: updatedUser!.createdAt
      }
    });
  } catch (error: any) {
    console.error("更新wxapp用户信息错误:", error);
    return res.status(500).json({ success: false, message: "服务器内部错误" });
  }
});

export default router;